package com.example.regular;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 正则表达式字符匹配
 * 关键（字符组和量词）
 * @author ZhenWuWang
 */
public class CharMatch
{
    public static void main(String[] args)
    {
//        lateralFuzzyMatch();
//        longitudinalFuzzyMatch();
//        scopeRex();
//        excludeChar();
//        greedyPattern();
//        inertiaPattern();
//        pinePattern();
//        case1();
//        case2();
//        case3();
//        case4();
        case5();
    }

    private static void stoutMatchResult(Matcher matcher)
    {
        while (matcher.find())
        {
            System.out.println(matcher.group());
        }
    }

    /**
     * 表示匹配这样一个字符串：第一个字符是“a”，接下来是2到5个字符“b”，最后是字符“c”
     */
    private static final Pattern LATERAL_FUZZY_PATTERN = Pattern.compile("ab{2,5}c");

    /**
     * 横向模糊匹配（一个字符多次匹配）
     * {m,n}，表示连续出现最少m次，最多n次。
     */
    private static void lateralFuzzyMatch()
    {
        Matcher matcher = LATERAL_FUZZY_PATTERN.matcher("abc abbc abbbc abbbbc abbbbbc abbbbbbc");
        stoutMatchResult(matcher);
    }


    /**
     * 可以匹配如下三种字符串：”a1b”、”a2b”、”a3b”
     */
    private static final Pattern LONGITUDINAL_FUZZY_PATTERN = Pattern.compile("a[123]b");

    /**
     * 纵向模糊匹配（一个匹配可能是多个字符）
     */
    private static void longitudinalFuzzyMatch()
    {
        Matcher matcher = LONGITUDINAL_FUZZY_PATTERN.matcher("a0b a1b a2b a3b a4b");
        stoutMatchResult(matcher);
    }


    /**
     * 可以匹配如下三种字符串：”a1b”、”a2b”、”a3b”
     */
    private static final Pattern LONGITUDINAL_FUZZY_SCOPEREX_PATTERN = Pattern.compile("a[1-3]b");

    /**
     * 字符组-范围表示法
     * 1.如果字符组里的字符特别多的话，怎么办？可以使用范围表示法，比如[123456abcdefGHIJKLM]，可以写成[1-6a-fG-M]。用连字符-来省略和简写。
     * 2.如果要匹配“a”、“-”、“z”这三者中任意一个字符，能写成[a-z]，因为其表示小写字符中的任何一个字符，可以写成如下的方式：[-az]或[az-]或[a\-z]
     */
    private static void scopeRex()
    {
        Matcher matcher = LONGITUDINAL_FUZZY_SCOPEREX_PATTERN.matcher("a0b a1b a2b a3b a4b");
        stoutMatchResult(matcher);
    }

    /**
     * 匹配除”a”、”b”、”c”之外的任意一个字符
     */
    private static final Pattern EXCLUDE_CHAR_PATTERN = Pattern.compile("[^abc]");

    private static void excludeChar()
    {
        Matcher matcher = EXCLUDE_CHAR_PATTERN.matcher("ad0bf1c");
        stoutMatchResult(matcher);
    }


    /**
     * 贪婪匹配
     * 匹配2-5个数字的字符，会尽可能的多匹配
     */
    private static final Pattern GREEDY_PATTERN = Pattern.compile("\\d{2,5}");

    private static void greedyPattern()
    {
        Matcher matcher = GREEDY_PATTERN.matcher("123 1234 12345 123456");
        stoutMatchResult(matcher);
    }

    /**
     * 惰性匹配
     * 匹配出现2-5个数字的字符，会进行最少匹配，但是只匹配到2个就算一次
     */
    private static final Pattern INERTIA_PATTERN = Pattern.compile("\\d{2,5}?");

    private static void inertiaPattern()
    {
        Matcher matcher = INERTIA_PATTERN.matcher("123 1234 12345 123456");
        stoutMatchResult(matcher);
    }

    /**
     * 管道模式，管道模式类似于或，前面的分支满足了，旧忽略后面的分支
     */
    private static final Pattern PINE_PATTERN = Pattern.compile("good|nice");
    private static final Pattern PINE_PATTERN_1 = Pattern.compile("good|goodbye");
    private static final Pattern PINE_PATTERN_2 = Pattern.compile("goodbye|good");

    private static void pinePattern()
    {
        Matcher matcher = PINE_PATTERN.matcher("good idea, nice try ");
        stoutMatchResult(matcher);
        System.out.println("-----------------------------------------------");
        matcher = PINE_PATTERN_1.matcher("goodbye");
        stoutMatchResult(matcher);
        System.out.println("-----------------------------------------------");
        matcher = PINE_PATTERN_2.matcher("good goodbye");
        stoutMatchResult(matcher);
    }

    /**
     * 匹配16进制颜色
     */
    private static final Pattern OX_COLOUR_PATTERN = Pattern.compile("#([0-9a-fA-f]{6}|[0-9a-fA-f]{3})");

    private static void case1()
    {
        Matcher matcher = OX_COLOUR_PATTERN.matcher("#ffbbad #Fc01DF #FFF #ffE #asda");
        stoutMatchResult(matcher);
    }

    /**
     * 24小时时间格式字符串匹配
     */
    private static final Pattern TIME_FORMAT_PATTERN = Pattern.compile("([01]\\d|[2][0-3]):[0-5]\\d");

    private static void case2()
    {
        Matcher matcher = TIME_FORMAT_PATTERN.matcher("23:59 02:0 23:591 02:07");
        stoutMatchResult(matcher);
    }

    /**
     * 日期匹配（yyyy-mm-dd）
     */
    private static final Pattern DATE_FORMAT_PATTERN = Pattern.compile("\\d{4}-(0\\d|1[0-2])-(0[1-9]|[1-2]\\d|3[01])");

    private static void case3()
    {
        Matcher matcher = DATE_FORMAT_PATTERN.matcher("2017-06-10 456-21-8 2017-12-01");
        stoutMatchResult(matcher);
    }

    /**
     * windows路径匹配
     * F:\study\javascript\regex\regular expression.pdf
     * <p>
     * F:\study\javascript\regex\
     * <p>
     * F:\study\javascript
     * <p>
     * F:\
     */
    private static final Pattern WIN_PATH_PATTERN = Pattern.compile("[a-zA-Z]:\\\\([^\\\\:*<>|\"?\\r\\n/]+\\\\)*([^\\\\:*<>|\"?\\r\\n/]+)?");

    private static void case4()
    {
        List<String> list = Arrays.asList("F:\\study\\javascript\\regex\\regular expression.pdf",
                "F:\\study\\javascript\\regex\\",
                "F:\\study\\javascript",
                "F:\\",
                "Aadssadsa");
        for (String path : list)
        {
            Matcher matcher = WIN_PATH_PATTERN.matcher(path);
            System.out.println("matcher: " + matcher.matches());
        }
    }

    /**
     * 匹配id="container"
     */
    private static final Pattern SUB_ID_PATTERN = Pattern.compile("id=\"[^\"]*\"");

    private static void case5()
    {
        Matcher matcher = SUB_ID_PATTERN.matcher("<div id=\"container\" class=\"main\"></div>");
        stoutMatchResult(matcher);
    }
}
